package com.fang.controller;


import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.api.R;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fang.common.enums.InvalidEnum;
import com.fang.common.wrapper.ResponseWrapper;
import com.fang.entity.SysRole;
import com.fang.entity.SysRoleMenu;
import com.fang.entity.SysUserRole;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author Fang Ruichuan
 * @since 2022-08-27
 */
@RestController
@RequestMapping("/sys/role")
public class SysRoleController extends BaseController {

    @GetMapping("/info/{id}")
    @PreAuthorize("hasAuthority('sys:role:info')")
    public ResponseWrapper info(@PathVariable("id") Long id) {
        SysRole sysRole = sysRoleService.getById(id);

        // 获取角色相关联的菜单id
        List<SysRoleMenu> roleMenus = sysRoleMenuService.list(Wrappers
                .<SysRoleMenu>lambdaQuery().eq(SysRoleMenu::getRoleId, id));
        List<Long> menuIds = roleMenus.stream().map(SysRoleMenu::getMenuId).collect(Collectors.toList());
        sysRole.setMenuIds(menuIds);
        return ResponseWrapper.success(sysRole);
    }

    @GetMapping("/list")
    @PreAuthorize("hasAuthority('sys:role:list')")
    public ResponseWrapper list(String name) {
        Page<SysRole> pageData = sysRoleService.page(getPage(),
                Wrappers.<SysRole>lambdaQuery()
                        .like(StringUtils.isNotBlank(name), SysRole::getName, name));
        return ResponseWrapper.success(pageData);
    }

    @PostMapping("/save")
    @PreAuthorize("hasAuthority('sys:role:save')")
    public ResponseWrapper save(@RequestBody @Validated SysRole sysRole) {
        sysRole.setCreated(LocalDateTime.now());
        sysRole.setStatus(InvalidEnum.STATUS_ON.getStatusCode());
        sysRoleService.save(sysRole);
        return ResponseWrapper.success();
    }

    @PostMapping("/update")
    @PreAuthorize("hasAuthority('sys:role:update')")
    public ResponseWrapper update(@RequestBody @Validated SysRole sysRole) {
        sysRole.setUpdated(LocalDateTime.now());
        sysRoleService.updateById(sysRole);

        // 更新缓存
        sysUserService.clearUserAuthorityInfoByRoleId(sysRole.getId());
        return ResponseWrapper.success();
    }

    @DeleteMapping("/delete")
    @Transactional(rollbackFor = Exception.class)
    @PreAuthorize("hasAuthority('sys:role:delete')")
    public ResponseWrapper delete(Long[] ids) {
        sysRoleService.removeByIds(Arrays.asList(ids));

        // 删除中间表
        sysUserRoleService.remove(Wrappers.<SysUserRole>lambdaQuery().in(SysUserRole::getRoleId, ids));
        sysRoleMenuService.remove(Wrappers.<SysRoleMenu>lambdaQuery().in(SysRoleMenu::getRoleId, ids));

        // 缓存同步删除
        Arrays.stream(ids).forEach(id -> {
            // 更新缓存
            sysUserService.clearUserAuthorityInfoByRoleId(id);
        });
        return ResponseWrapper.success();
    }

    @GetMapping("/perm/{roleId}")
    @Transactional(rollbackFor = Exception.class)
    @PreAuthorize("hasAuthority('sys:role:perm')")
    public ResponseWrapper perm(@PathVariable("roleId") Long roleId, Long[] menuIds) {
        List<SysRoleMenu> sysRoleMenus = new LinkedList<>();
        Arrays.stream(menuIds).forEach(menuId -> {
            sysRoleMenus.add(SysRoleMenu.builder()
                    .menuId(menuId)
                    .roleId(roleId)
                    .build());
        });
        // 先删除原来的记录, 再保存新的
        sysRoleMenuService.remove(Wrappers.<SysRoleMenu>lambdaQuery().eq(SysRoleMenu::getRoleId, roleId));
        sysRoleMenuService.saveBatch(sysRoleMenus);

        // 删除缓存
        sysUserService.clearUserAuthorityInfoByRoleId(roleId);
        return ResponseWrapper.success();
    }

}
